﻿Imports DevExpress

Public Class frmHours
    Private thisEmp As Employee
    Private _AllEmployees As EmployeeList
    Private CurSkin As Skins.Skin
    Public Sub New(ByVal emp As Employee, ByVal AllEmployees As EmployeeList, ByVal Skin As Skins.Skin, Optional ByVal Day As Integer = -1)

        ' This call is required by the Windows Form Designer.
        thisEmp = emp
        InitializeComponent()
        _AllEmployees = AllEmployees
        For Each dy As Day In thisEmp.Days
            cboDays.Properties.Items.Add(dy)
        Next
        cboDays.SelectedIndex = 1

        ' Add any initialization after the InitializeComponent() call.

        If Day >= 0 Then cboDays.SelectedIndex = Day
        Me.Text = emp.Name & " Hours"
        CurSkin = Skin
       
        'DefaultLookAndFeel1.LookAndFeel.SkinName = My.Settings.FormTheme
        dtHire.EditValue = emp.HireDate
        dtFire.EditValue = emp.FireDate
        dtpException.DateTime = Now.Date
        With dtStart
            .DateTime = AllEmployees.WorkHours.getMinStartTime(cboDays.SelectedIndex)
            .Properties.MinValue = AllEmployees.WorkHours.SemesterStart
            .Properties.MaxValue = AllEmployees.WorkHours.SemesterEnd
        End With
        With dtEnd
            .DateTime = AllEmployees.WorkHours.getMaxEndTime(cboDays.SelectedIndex)
            .Properties.MinValue = AllEmployees.WorkHours.SemesterStart
            .Properties.MaxValue = AllEmployees.WorkHours.SemesterEnd
        End With
        txtEmployeeType.Properties.Items.AddRange(AllEmployees.GetUniqueEmployeeTypes())
        txtEmployeeType.EditValue = thisEmp.EmployeeType
        mruScheduleType.EditValue = thisEmp.EmployeeType
        mruScheduleType.Properties.Items.AddRange(AllEmployees.GetUniqueScheduleTypes())
        mruDefaultLocation.Properties.Items.AddRange(AllEmployees.GetUniqueLocations)
        mruLocation.Properties.Items.AddRange(AllEmployees.GetUniqueLocations)
        mruLocation.EditValue = thisEmp.DefaultLocation
        mruDefaultLocation.EditValue = thisEmp.DefaultLocation

    End Sub
    Private HaveLoaded As Boolean = False

    Private Sub frmHours_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        clrEmployee.ToolTip = clrEmployee.ToolTip.Replace("%", thisEmp.Name)
        dtpException.DateTime = Now.Date

        LoadHours()
        clrEmployee.EditValue = thisEmp.Color
        txtEmployeeName.Text = thisEmp.Name
        HaveLoaded = True
    End Sub

    Private Sub btnAddTime_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddTime.Click
        Dim dy As Day = cboDays.SelectedItem
        If Not ValidateWorkTime() Then Return

        dy.AddTimeRange(dtStart.DateTime, dtEnd.DateTime, mruScheduleType.EditValue, mruLocation.EditValue)

        LoadHours()
    End Sub
    Private Sub LoadHours()
        If TypeOf cboDays.SelectedItem Is String AndAlso cboDays.SelectedItem = "" Then Return
        Dim dy As Day = cboDays.SelectedItem
        lbTimes.Items.Clear()

        For x As Integer = 0 To dy.StartTimes.Length - 1

            lbTimes.Items.Add(String.Format("{2} {0}-{3} {1}", dy.StartTimes(x).ToShortTimeString, dy.EndTimes(x).ToShortTimeString, dy.StartTimes(x).ToShortDateString, dy.EndTimes(x).ToShortDateString))


        Next
        For Each tr As TimeRangeException In dy.TimeExceptions
            lbTimes.Items.Add(tr)
        Next
        For Each hi As HolidayInfo In (From h1 As HolidayInfo In thisEmp.Holidays Order By h1.Day).Concat(From h2 As HolidayInfo In _AllEmployees.Holidays Order By h2.Day)


            lbTimes.Items.Add(hi)

        Next
        
        'Dim g As Graphics = lbTimes.CreateGraphics
        'Dim sz As Single = 0
        'Dim fnt As New Font(lbTimes.Font, FontStyle.Bold)
        'For x As Integer = 0 To lbTimes.Items.Count - 1
        '    sz = Math.Max(sz, g.MeasureString(lbTimes.Items(x).ToString, fnt).Width)

        'Next

        'lbTimes.HorizontalScrollbar = sz > lbTimes.Width


        'btnRemoveTime.Enabled = False
        'If dtpException.Value.DayOfWeek = cboDays.SelectedIndex Then
        '    btnAddException.Enabled = True
        'Else
        '    btnAddException.Enabled = False
        'End If
    End Sub

    Private Sub cboDays_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboDays.SelectedIndexChanged
        LoadHours()
    End Sub

    Private Sub btnRemoveTime_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnRemoveTime.Click
        If lbTimes.SelectedIndex = -1 Then Return
        If TypeOf lbTimes.SelectedItem Is String Then
            Dim dy As Day = cboDays.SelectedItem
            dy.RemoveTimeRange(lbTimes.SelectedIndex)
        ElseIf TypeOf lbTimes.SelectedItem Is TimeRangeException Then
            Dim dy As Day = cboDays.SelectedItem
            dy.TimeExceptions.Remove(lbTimes.SelectedItem)

        Else
            Dim hi As HolidayInfo = lbTimes.SelectedItem
            If hi.IsGeneralHoliday Then
                _AllEmployees.Holidays.Remove(hi)
            Else
                thisEmp.Holidays.Remove(lbTimes.SelectedItem)
            End If


        End If

        LoadHours()
    End Sub

    Private Sub dtEnd_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dtStart.EditValueChanged, dtEnd.EditValueChanged
        Dim tmpdate As Date = New Date(dtEnd.EditValue.Year, dtEnd.EditValue.Month, dtEnd.EditValue.Day, dtStart.EditValue.Hour, dtStart.EditValue.Minute, dtStart.EditValue.Second)

        If dtEnd.EditValue < dtStart.EditValue Then
            btnAddTime.Enabled = False
            btnUpdate.Enabled = False

        Else
            btnAddTime.Enabled = True
            If TypeOf lbTimes.SelectedItem Is String Then

                If lbTimes.SelectedIndex >= 0 Then btnUpdate.Enabled = True
            End If
        End If
    End Sub

    'Private Sub lbTimes_MeasureItem(sender As Object, e As System.Windows.Forms.MeasureItemEventArgs) Handles lbTimes.MeasureItem
    '    Dim fnt As Font = New Font(lbTimes.Appearance.Font, FontStyle.Bold)

    '    e.ItemWidth = e.Graphics.MeasureString(lbTimes.Items(e.Index).ToString, fnt).Width

    'End Sub

    

    'Private Sub lbTimes_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    '    Debug.WriteLine(lbTimes.IndexFromPoint(e.Location))
    '    If lbTimes.IndexFromPoint(e.Location) = -1 Then
    '        ttp.SetToolTip(lbTimes, "")
    '    Else
    '        Dim index As Integer = lbTimes.IndexFromPoint(e.Location)
    '        Dim rec As Rectangle = lbTimes.GetItemRectangle(index)
    '        If rec.Contains(e.Location) Then
    '            ttp.SetToolTip(lbTimes, lbTimes.Items(index).ToString)
    '        Else
    '            ttp.SetToolTip(lbTimes, "")
    '        End If



    '    End If
    'End Sub



    Private Sub lbTimes_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles lbTimes.SelectedIndexChanged
        If lbTimes.SelectedIndex = -1 Then
            btnRemoveTime.Enabled = False
            btnUpdate.Enabled = False
            btnHUpdate.Enabled = False
            grpSplit.Enabled = False
        Else
            If TypeOf lbTimes.SelectedItem Is String Then
                Dim dy As Day = cboDays.SelectedItem


                dtStart.EditValue = dy.StartTimes(lbTimes.SelectedIndex)
                dtEnd.EditValue = dy.EndTimes(lbTimes.SelectedIndex)
                mruLocation.EditValue = dy.Locations(lbTimes.SelectedIndex)
                mruScheduleType.EditValue = dy.ScheduleEmployeeTypes(lbTimes.SelectedIndex)
                btnHUpdate.Enabled = False
                btnUpdate.Enabled = True
                btnRemoveTime.Enabled = True


                grpSplit.Enabled = True
                With dtSplit.Properties
                    .MinValue = dy.StartTimes(lbTimes.SelectedIndex)
                    .MaxValue = dy.EndTimes(lbTimes.SelectedIndex)

                End With
                
            ElseIf TypeOf lbTimes.SelectedItem Is TimeRangeException Then

                btnRemoveTime.Enabled = True
                btnUpdate.Enabled = False
                btnHUpdate.Enabled = False
                grpSplit.Enabled = False
                Dim tre As TimeRangeException = lbTimes.SelectedItem

                cboExceptionType.SelectedIndex = tre.ExceptionType
                dtStart.DateTime = tre.StartTime
                dtEnd.DateTime = tre.EndTime
                dtpException.DateTime = tre.Day
                mruScheduleType.EditValue = tre.ScheduleType
                mruLocation.EditValue = tre.Location
                If cboExceptionType.SelectedIndex = 1 Then btnAddException.Enabled = True


            Else
                grpSplit.Enabled = False
                btnRemoveTime.Enabled = True
                btnUpdate.Enabled = False
                btnHUpdate.Enabled = True

                Dim hi As HolidayInfo = lbTimes.SelectedItem
                dtHoliday.DateTime = hi.Day
                If hi.EndDate.HasValue Then
                    dtHolidayEnd.DateTime = hi.EndDate
                Else
                    dtHolidayEnd.EditValue = Nothing


                End If
                txtHCaption.Text = hi.Caption
                chkAllEmployees.Checked = hi.IsGeneralHoliday
                If cboExceptionType.SelectedIndex = 1 Then btnAddException.Enabled = True

            End If
        End If
        UpdateExceptionState()

    End Sub
    Private Sub UpdateExceptionState()
        'states for exceptions
        'replace type
        '->work time selected/not selected
        'Add type
        'DeleteType
        If cboExceptionType.SelectedIndex = ExceptionTypes.Replace Or cboExceptionType.SelectedIndex = ExceptionTypes.Delete Then
            If lbTimes.SelectedItem IsNot Nothing Then
                If Not TypeOf lbTimes.SelectedItem Is String Then
                    btnAddException.Enabled = False
                Else
                    btnAddException.Enabled = True

                End If
            Else
                btnAddException.Enabled = False
            End If
        Else
            btnAddException.Enabled = True
        End If


    End Sub
    Private Function ValidateWorkTime() As Boolean
        Dim st, en As Date
        en = dtEnd.DateTime
        st = GetNextDay(cboDays.SelectedIndex, dtStart.DateTime.Date)
        en = New Date(st.Year, st.Month, st.Day, en.Hour, en.Minute, en.Second)

        Dim work As XtraScheduler.TimeInterval = _AllEmployees.WorkHours.DayToWorkingTimeInterval(st, True)


        If work.Start.TimeOfDay > dtStart.DateTime.TimeOfDay OrElse work.End.TimeOfDay < en.TimeOfDay Then
            XtraEditors.XtraMessageBox.Show("For " & cboDays.Text & "s the work time must be between " & work.Start.ToShortTimeString & " and " & work.End.ToShortTimeString & ".", "Invalid Work Time", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)

            Return False
        End If
        Return True
    End Function
    Private Sub btnUpdate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnUpdate.Click

        If TypeOf lbTimes.SelectedItem Is String Then
            Dim dy As Day = cboDays.SelectedItem
            If Not ValidateWorkTime() Then Return
            Dim exc As List(Of TimeRangeException) = (From ex In dy.TimeExceptions Where ex.TimeRange = lbTimes.SelectedIndex).ToList
            'Dim old As New DevExpress.XtraScheduler.TimeInterval(dy.StartTimes(lbTimes.SelectedIndex), dy.EndTimes(lbTimes.SelectedIndex))

            dy.RemoveTimeRange(lbTimes.SelectedIndex)


            dy.AddTimeRange(dtStart.DateTime, dtEnd.DateTime, mruScheduleType.EditValue, mruLocation.EditValue)
            Dim ti As New DevExpress.XtraScheduler.TimeInterval(dtStart.DateTime, dtEnd.DateTime)
            For Each ex In exc
                Dim exti As New DevExpress.XtraScheduler.TimeInterval(ex.StartTime, ex.EndTime)
                If ti.IntersectsWith(exti) Then
                    dy.TimeExceptions.Add(ex)
                End If
            Next
            Dim i As Integer = lbTimes.SelectedIndex
            LoadHours()
            lbTimes.SelectedIndex = i
        End If
    End Sub

    Private Sub btnAddHoliday_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddHoliday.Click
        If CheckHolidayRange() Then
            Dim hi As New HolidayInfo(dtHoliday.DateTime.Date, dtHolidayEnd.EditValue, txtHCaption.Text, chkAllEmployees.Checked)
            If hi.IsGeneralHoliday Then
                _AllEmployees.Holidays.Add(hi)
                _AllEmployees.Holidays.Sort()

            Else
                thisEmp.Holidays.Add(hi)
                thisEmp.Holidays.Sort()
            End If

            LoadHours()
            lbTimes.SelectedItem = hi
        Else
            XtraEditors.XtraMessageBox.Show("Please check the holiday start and end date range.  Start must be before the end date.", "Invalid Holiday Range", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        End If

    End Sub

    Private Sub btnHUpdate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnHUpdate.Click
        If Not CheckHolidayRange() Then
            XtraEditors.XtraMessageBox.Show("Please check the holiday start and end date range.  Start must be before the end date.", "Invalid Holiday Range", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Return

        End If
        Dim index As Integer = lbTimes.SelectedIndex
        Dim hi As HolidayInfo = lbTimes.SelectedItem
        If hi.IsGeneralHoliday Then
            _AllEmployees.Holidays.Remove(hi)
        Else
            thisEmp.Holidays.Remove(lbTimes.SelectedItem)
        End If
        hi = New HolidayInfo(dtHoliday.DateTime.Date, dtHolidayEnd.EditValue, txtHCaption.Text, chkAllEmployees.Checked)
        If hi.IsGeneralHoliday Then
             _AllEmployees.Holidays.Add(hi)
            _AllEmployees.Holidays.Sort()
        Else
            thisEmp.Holidays.Add(hi)
            thisEmp.Holidays.Sort()
        End If

        LoadHours()
        lbTimes.SelectedItem = hi

    End Sub

    Private Sub btnAddException_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddException.Click
        Dim index As Integer = lbTimes.SelectedIndex
        Dim dayw As DayOfWeek = dtpException.DateTime.DayOfWeek
        If dayw <> cboDays.SelectedIndex Then
            cboDays.SelectedIndex = dayw
            If cboExceptionType.SelectedIndex = 0 Then
                XtraEditors.XtraMessageBox.Show("Please click add exception again after selecting the work time to apply the exception to.", "Different day and Date Selected", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                Return
            End If


        End If

        Dim dy As Day = cboDays.SelectedItem
        If Not ValidateWorkTime() Then Return

        Dim sdt As Date = New Date(dtpException.DateTime.Year, dtpException.DateTime.Month, dtpException.DateTime.Day, dtStart.DateTime.Hour, dtStart.DateTime.Minute, 0)
        Dim edt As Date = New Date(dtpException.DateTime.Year, dtpException.DateTime.Month, dtpException.DateTime.Day, dtEnd.DateTime.Hour, dtEnd.DateTime.Minute, 0)
        If edt <= sdt Then
            XtraEditors.XtraMessageBox.Show("Start time must be less than end time.  Please adjust the time and try again.", "Invalid Exception Time", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Return

        End If
        dy.TimeExceptions.Add(New TimeRangeException(dtpException.DateTime.Date, sdt, edt, lbTimes.SelectedIndex, mruScheduleType.EditValue, mruLocation.EditValue, cboExceptionType.SelectedIndex))
        LoadHours()
    End Sub

    Private Sub dtpException_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dtpException.EditValueChanged
        If lbTimes.SelectedItem Is Nothing Then
            btnAddException.Enabled = False
            Return
        End If
        If TypeOf lbTimes.SelectedItem Is String Then
            btnAddException.Enabled = True
        Else
            btnAddException.Enabled = False
        End If

    End Sub



    Private Sub lbTimes_DrawItem(ByVal sender As System.Object, ByVal e As XtraEditors.ListBoxDrawItemEventArgs) Handles lbTimes.DrawItem

        Dim brsh As SolidBrush = New SolidBrush(e.Appearance.ForeColor)
        Dim fnt As Font = e.Appearance.Font
        If TypeOf lbTimes.Items(e.Index) Is HolidayInfo Then
            Dim hi As HolidayInfo = lbTimes.Items(e.Index)
            brsh = Brushes.Red
            If hi.IsGeneralHoliday Then fnt = New Font(fnt, FontStyle.Bold)
        ElseIf TypeOf lbTimes.Items(e.Index) Is TimeRangeException Then
            brsh = Brushes.Orange
        End If

        Try

            Using hbrsh As New SolidBrush(CurSkin.TranslateColor(SystemColors.Highlight))

                'Dim textRect As New Rectangle(e.Bounds.X + 15, e.Bounds.Y, e.Bounds.Width - 15, e.Bounds.Height)
                If e.State And DrawItemState.Selected <> 0 Then e.Graphics.FillRectangle(hbrsh, e.Bounds)
            End Using
            e.Graphics.DrawString(lbTimes.Items(e.Index).ToString, fnt, brsh, e.Bounds.X, e.Bounds.Y)
        Catch ex As ArgumentException
            'Stop

        Catch ex As Exception
        End Try

        'brsh.Dispose()
        'e.DrawFocusRectangle()

        e.Handled = True
    End Sub

    Private Sub clrEmployee_EditValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles clrEmployee.EditValueChanged
        thisEmp.Color = clrEmployee.Color
    End Sub

    Private Sub lnkColorUnselect_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles lnkColorUnselect.LinkClicked
        clrEmployee.EditValue = Nothing
        thisEmp.Color = Nothing
    End Sub

    Private Sub cboExceptionType_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboExceptionType.SelectedIndexChanged
        UpdateExceptionState()
    End Sub

   

   
    Private Function CheckHolidayRange() As Boolean
        If dtHolidayEnd.EditValue IsNot Nothing Then
            If dtHoliday.EditValue > dtHolidayEnd.EditValue Then
                dtHolidayEnd.ErrorText = "This date cannot be before the date in the beginning date."
                Return False
            Else
                dtHolidayEnd.ErrorText = ""
                Return True

            End If
        Else
            dtHolidayEnd.ErrorText = ""
            Return True
        End If
    End Function

    Private Sub dtHoliday_EditValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dtHoliday.EditValueChanged
        CheckHolidayRange()
    End Sub

    Private Sub dtHolidayEnd_EditValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dtHolidayEnd.EditValueChanged
        CheckHolidayRange()
    End Sub

    
    Private Sub dtHire_EditValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dtHire.EditValueChanged
        If dtHire.EditValue IsNot Nothing Then
            dtpException.Properties.MinValue = dtHire.DateTime
        Else
            dtpException.Properties.MinValue = Date.MinValue

        End If
        If HaveLoaded Then thisEmp.HireDate = dtHire.EditValue
    End Sub

    Private Sub dtFire_EditValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dtFire.EditValueChanged
        If dtFire.EditValue IsNot Nothing Then
            dtpException.Properties.MaxValue = dtFire.DateTime

        Else
            dtpException.Properties.MaxValue = Date.MaxValue

        End If
        If HaveLoaded Then thisEmp.FireDate = dtFire.EditValue

    End Sub

    Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
        If Not String.IsNullOrEmpty(txtEmployeeName.Text) AndAlso Not String.IsNullOrEmpty(txtEmployeeName.Text.Trim) Then thisEmp.Name = txtEmployeeName.Text


        thisEmp.EmployeeType = txtEmployeeType.Text
        thisEmp.DefaultLocation = mruDefaultLocation.EditValue
       
    End Sub

    Private Sub dtStart_Properties_ButtonClick(sender As System.Object, e As DevExpress.XtraEditors.Controls.ButtonPressedEventArgs) Handles dtStart.Properties.ButtonClick
        If e.Button.Kind = XtraEditors.Controls.ButtonPredefines.Left Then
            dtStart.DateTime = Me._AllEmployees.WorkHours.getMinStartTime(cboDays.SelectedIndex)
        End If
    End Sub

    Private Sub dtEnd_Properties_ButtonClick(sender As System.Object, e As DevExpress.XtraEditors.Controls.ButtonPressedEventArgs) Handles dtEnd.Properties.ButtonClick
        If e.Button.Kind = XtraEditors.Controls.ButtonPredefines.Right Then
            dtEnd.DateTime = Me._AllEmployees.WorkHours.getMaxEndTime(cboDays.SelectedIndex)
        End If
    End Sub

    
    
    Private Sub btnSplit_Click(sender As System.Object, e As System.EventArgs) Handles btnSplit.Click
        Dim dy As Day = cboDays.SelectedItem
        dy.SplitSchedule(lbTimes.SelectedIndex, dtSplit.DateTime.Date)
        LoadHours()
    End Sub

End Class